package com.helloniu.fl {

import com.helloniu.fl.util.Tool;
import flash.events.*;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Microphone;
import flash.media.Camera;

/***
 var publishHandler:NSHandler = new NSHandler(netConn);
 publishHandler.setStreamName("aa");
 publishHandler.setStartPublishFunc(startPublishFunc);
 publishHandler.publish(micphone, camera);

 function startPublishFunc(apublishHandler:NSHandler):void {
    // do something
 }

 --or--
 var playHandler:NSHandler = new NSHandler(nc);
 playHandler.setStreamName("aa");
 playHandler.setStartPlayFunc(startPlayFunc);
 playHandler.play();

 function startPlayFunc(aplayHandler:NSHandler):void {
    // do something
 }

**/
public class NSHandler {
    public function NSHandler(anetConnection:NetConnection) {
        this.netConnection = anetConnection;

        initStream();
    }

    public function getStream():NetStream {
        return this.netStream;
    }

    public function setStartPublishFunc(astartPublishFunc:Function):void {
        this.startPublishFunc = astartPublishFunc;
    }

    public function setStartPlayFunc(astartPlayFunc:Function):void {
        this.startPlayFunc = astartPlayFunc;
    }

    public function setStreamName(astreamName:String):void {
        this.streamName = astreamName;
    }

    public function getStreamName():String {
        return this.streamName;
    }

    public function closeStream():void {
        var events:Array = eventsToHandle;
        var n:int = events.length;

        for(var i:int = 0; i < n; i++) {
            netStream.removeEventListener(events[i], eventHandler);
        }

        netStream.close();
    }

    private function initStream():void {
        this.netStream = new NetStream(this.netConnection);

        var events:Array = eventsToHandle;
        var n:int = events.length;

        for(var i:int = 0; i < n; i++) {
            netStream.addEventListener(events[i], eventHandler, false, 0, false);
        }
    }

    public function publish(microp:Microphone, camera:Camera,
        atype:String = "live"):void
    {
        if(microp != null) {
            this.netStream.attachAudio(microp);
        }

        if(camera != null) {
            this.netStream.attachCamera(camera);
        }

        this.netStream.publish(getStreamName(), atype);
    }
    
    public function play(audio:Boolean = true, video:Boolean = true,
        bufTime:int = 0):void
    {
        this.netStream.bufferTime = bufTime;
        this.netStream.receiveAudio(audio);
        this.netStream.receiveVideo(video);

        this.netStream.play(getStreamName());
    }

    /**
     * Net status handler.
     */
    private function eventHandler(event:Event):void {
        var etype:String = event.type;
        var events:Array = eventsToHandle;

        if(etype == NetStatusEvent.NET_STATUS) {
            var levelVal:String = (event as NetStatusEvent).info.level;

            if(levelVal == "error") {
                // show error
                return;
            }

            // levelVal == "status"
            var statusCode:String = (event as NetStatusEvent).info.code;
            var startPublish:String = "NetStream.Publish.Start";
            var startPlay:String = "NetStream.Play.Start";

            if(statusCode == startPublish && startPublishFunc != null) {
                (startPublishFunc as Function).call(null, this);
            }
            else if(statusCode == startPlay && startPlayFunc != null) {
                (startPlayFunc as Function).call(null, this);
            }
        }
    }

    /**
     * Strings of the events to listen for.
     */
    private function get eventsToHandle():Array {
        return [ NetStatusEvent.NET_STATUS, AsyncErrorEvent.ASYNC_ERROR,
            IOErrorEvent.IO_ERROR, "onCuePoint", "onMetaData", "onPlayStatus" ];
    }

    private var netConnection:NetConnection = null;
    private var netStream:NetStream = null;
    private var startPublishFunc:Function = null;
    private var startPlayFunc:Function = null;
    private var streamName:String = null;
}
}